home *** CD-ROM | disk | FTP | other *** search
- /*
- * kaffe2native.c
- * This program reads in a kaffe.def file and converts it to the necessary
- * source files for the kaffe machine.
- *
- * Copyright (c) 1996 Systems Architecture Research Centre,
- * City University, London, UK.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * Written by Tim Wilkinson <tim@sarc.city.ac.uk>, February 1996.
- */
-
- #include <stdio.h>
-
- void openFiles(void);
- void process(void);
- void processInstruction(void);
- void processRegister(void);
- void processOpcodes(void);
- void getLine(void);
- void skipSpace(void);
- void finish(void);
-
- #define SHEADER \
- "/*\n\
- * instn.c\n\
- * Real instruction and register information.\n\
- */\n\
- \n\
- #include \"instruction.h\"\n\
- #include \"register.h\"\n\
- #include \"gen.h\"\n\
- \n\
- /*\n\
- * Declare the translation between Kaffe VM instructions and native instructions.\n\
- */\n\
- nativeInstn instnTable[256] = {\n\
- \n\
- /* in, out, size, emulate, code */\n"
-
- #define GHEADER \
- "/*\n\
- * gen.c\n\
- * Generated instruction sequences.\n\
- */\n\
- \n\
- #include <assert.h>\n\
- #include \"instruction.h\"\n\
- #include \"soft.h\"\n\
- #include \"asm.h\"\n\
- \n\
- void gen_UNKNOWN(instn* i)\n\
- {\n\
- }\n\
- \n"
-
- #define GHEADERH \
- "/*\n\
- * gen.h\n\
- * Generated instruction sequences.\n\
- */\n\
- \n\
- typedef void (*genfunc)(instn*);\n\
- \n\
- void gen_UNKNOWN(instn*);\n\
- "
-
- #define BHEADERH \
- "/*\n\
- * bytecode.h\n\
- * Generate bytecode defines.\n\
- */\n\
- \n\
- #ifndef __bytecode_h\n\
- #define __bytecode_h\n\
- \n\
- typedef unsigned char bytecode;\n\
- \n"
-
- #define MAXREG 64
- #define MAXOP 256
-
- #define MAXBUF 200
-
- #define SOUT "instn.c"
- #define GOUT "gen.c"
- #define GOUTH "gen.h"
- #define BOUTH "bytecode.h"
-
- FILE* in;
- FILE* sout;
- FILE* gout;
- FILE* gouth;
- FILE* bouth;
-
- int line;
- char* buf;
- int regno;
-
- char opcode[MAXOP][MAXBUF];
- char regs[MAXREG][MAXBUF];
-
- main(int c, char* argv[])
- {
- char* input = "kaffe.def";
- if (c == 2) {
- input = argv[1];
- }
- in = fopen(input, "r");
- if (in == 0) {
- fprintf(stderr, "Cannot find %s\n", input);
- exit(1);
- }
- openFiles();
- fputs(SHEADER, sout);
- fputs(GHEADER, gout);
- fputs(GHEADERH, gouth);
- fputs(BHEADERH, bouth);
- process();
- finish();
- exit(0);
- }
-
- void
- openFiles(void)
- {
- sout = fopen(SOUT, "w");
- if (sout == 0) {
- fprintf(stderr, "Cannot create %s\n", SOUT);
- exit(1);
- }
- gout = fopen(GOUT, "w");
- if (gout == 0) {
- fprintf(stderr, "Cannot create %s\n", GOUT);
- exit(1);
- }
- gouth = fopen(GOUTH, "w");
- if (gouth == 0) {
- fprintf(stderr, "Cannot create %s\n", GOUTH);
- exit(1);
- }
- bouth = fopen(BOUTH, "w");
- if (bouth == 0) {
- fprintf(stderr, "Cannot create %s\n", BOUTH);
- exit(1);
- }
- }
-
- void
- process(void)
- {
- while (getLine(), buf != 0) {
- if (buf[0] == '#' || isspace(buf[0])) {
- continue;
- }
- else if (strncmp(buf, "insn", 4) == 0) {
- processInstruction();
- }
- else if (strncmp(buf, "reg", 3) == 0) {
- processRegister();
- }
- else {
- fprintf(stderr, "Bad data at line %d\n", line);
- exit(1);
- }
- }
- }
-
- /*
- * eg. insn FADD(in=float,float; out=float; sync) = 98
- */
- void
- processInstruction(void)
- {
- char* name;
- char* type;
- int ins;
- int outs;
- int op;
- int soft;
-
- type = "i_hard";
-
- buf += 4;
- skipSpace();
-
- name = buf;
- for (; *buf != 0; buf++) {
- if (*buf == '(' || isspace(*buf)) {
- *buf = 0;
- buf++;
- goto inout;
- }
- }
- fprintf(stderr, "Bad instruction format at line %d\n", line);
- exit(1);
-
- inout:
- for(;;) {
- skipSpace();
- if (buf[0] == ')') {
- buf++;
- break;
- }
-
- if (strncmp(buf, "in=", 3) == 0) {
- buf += 3;
- ins = countTypes();
- }
- else if (strncmp(buf, "out=", 4) == 0) {
- buf += 4;
- outs = countTypes();
- }
- else if (strncmp(buf, "sync", 4) == 0) {
- buf += 4;
- type = "i_sync";
- soft = 1;
- }
- else if (strncmp(buf, "soft", 4) == 0) {
- buf += 4;
- type = "i_soft";
- soft = 1;
- }
- else if (strncmp(buf, "hard", 4) == 0) {
- buf += 4;
- type = "i_hard";
- soft = 0;
- }
- }
-
- skipSpace();
- if (buf[0] == '=') {
- buf++;
- }
- skipSpace();
- op = atoi(buf);
- if (op >= MAXOP) {
- fprintf(stderr, "Opcode too big at line %d\n", line);
- exit(1);
- }
-
- /* Supress ins and outs for sync and soft instructions */
- if (soft == 1) {
- ins = 0;
- outs = 0;
- }
-
- sprintf(opcode[op], " { %d, %d, %d, %s, gen_%s },\n",
- ins, outs, 0, type, name);
-
- getLine();
- if (buf[0] != '{') {
- fprintf(stderr, "No code body at line %d\n", line);
- exit(1);
- }
-
- fprintf(gouth, "void gen_%s(instn*);\n", name);
- fprintf(gout, "void gen_%s(instn* i)\n{\n", name);
- fprintf(bouth, "#define %s %d\n", name, op);
- for (;;) {
- getLine();
- if (buf[0] == '}') {
- break;
- }
- processOpcodes();
- }
- fprintf(gout, "}\n\n");
- }
-
- void
- processOpcodes(void)
- {
- int i;
- int j;
- int a;
- char obuf[MAXBUF];
- char abuf[MAXBUF];
- int r;
-
- /* First handle literal escapes */
- if (buf[0] == '+') {
- buf++;
- skipSpace();
- fprintf(gout, "\t%s", buf);
- return;
- }
-
- skipSpace();
-
- /* Process opcode to something we can use as a function name */
- j = 0;
- i = 0;
- a = 0;
- abuf[0] = 0;
- while (buf[i] != 0) {
- switch (buf[i++]) {
- /* Input register */
- case 'I':
- case 'W':
- case 'B':
- r = buf[i++] - '1';
- sprintf(&abuf[a], "i->in[%d].reg->regno,", r);
- obuf[j++] = 'R';
- break;
-
- /* Output register */
- case 'O':
- r = buf[i++] - '1';
- sprintf(&abuf[a], "i->out[%d].reg->regno,", r);
- obuf[j++] = 'R';
- break;
-
- /* Local constant */
- case 'C':
- /* Integer value */
- case 'V':
- r = buf[i++] - '1';
- sprintf(&abuf[a], "i->value[%d],", r);
- obuf[j++] = 'V';
- break;
-
- /* Local variable */
- case 'L':
- r = buf[i++] - '1';
- sprintf(&abuf[a], "4*(i->value[%d]),REG_BASE,", r);
- obuf[j++] = 'V';
- obuf[j++] = 'o';
- obuf[j++] = 'R';
- obuf[j++] = 'o';
- break;
-
- /* Stack value */
- case 'S':
- r = buf[i++] - '1';
- sprintf(&abuf[a], "4*%d,REG_STACK,", r);
- obuf[j++] = 'V';
- obuf[j++] = 'o';
- obuf[j++] = 'R';
- obuf[j++] = 'o';
- break;
-
- /* Jump address */
- case 'J':
- sprintf(&abuf[a], "i->value[0],");
- obuf[j++] = 'J';
- break;
-
- /* Jump to absolute address */
- case 'X':
- sprintf(&abuf[a], "i->value[0],");
- obuf[j++] = 'X';
- break;
-
- case ',':
- obuf[j++] = 'x';
- break;
-
- case '(':
- case ')':
- obuf[j++] = 'o';
- break;
-
- case ' ':
- case '\t':
- obuf[j++] = '_';
- break;
-
- case '$':
- case '\n':
- break;
-
- case '*':
- obuf[j++] = 's';
- break;
-
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- case '-':
- i--;
- while (isxdigit(buf[i]) ||
- buf[i] == '-' || buf[i] == 'x') {
- abuf[a] = buf[i];
- i++;
- a++;
- }
- sprintf(&abuf[a], ",");
- obuf[j++] = 'V';
- break;
-
- /* Specific register name */
- case '%':
- sprintf(&abuf[a], "REG_");
- a += 4;
- while (isalnum(buf[i])) {
- abuf[a] = buf[i];
- i++;
- a++;
- }
- sprintf(&abuf[a], ",");
- obuf[j++] = 'R';
- break;
-
- /* Soft routine calls */
- case '_':
- if (strncmp(&buf[i], "soft", 4) != 0) {
- obuf[j++] = buf[i-1];
- }
- else {
- sprintf(&abuf[a], "(int)");
- a += 5;
- while (isalnum(buf[i]) ||
- buf[i] == '_') {
- abuf[a] = buf[i];
- i++;
- a++;
- }
- sprintf(&abuf[a], ",");
- obuf[j++] = 'X';
- }
- break;
-
- default:
- obuf[j++] = buf[i-1];
- while (isalnum(buf[i])) {
- obuf[j++] = buf[i++];
- }
- break;
- }
- a = strlen(abuf);
- }
- obuf[j] = 0;
- for (j--; obuf[j] == '_'; j--) {
- obuf[j] = 0;
- }
- if (a > 0 && abuf[a-1] == ',') {
- abuf[a-1] = 0;
- }
-
- fprintf(gout, "\tasm__%s(%s);\n", obuf, abuf);
- }
-
- /*
- * eg. reg %eax int = 0
- */
- void
- processRegister(void)
- {
- char* name;
- char* type;
- char* nr;
-
- buf += 3;
- skipSpace();
- name = buf;
- for (; *buf != 0; buf++) {
- if (*buf == ',' || isspace(*buf)) {
- *buf = 0;
- buf++;
- goto wn;
- }
- }
- fprintf(stderr, "Bad register format at line %d\n", line);
- exit(1);
-
- wn:
- /* Skip type definition */
- skipSpace();
- type = buf;
- for (; *buf != 0; buf++) {
- if (*buf == ',' || isspace(*buf)) {
- *buf = 0;
- buf++;
- goto nn;
- }
- }
- fprintf(stderr, "Bad register format at line %d\n", line);
- exit(1);
-
- nn:
- skipSpace();
- buf++; /* Skip = */
- skipSpace();
- nr = buf;
-
- if (regno >= MAXREG) {
- fprintf(stderr, "Register number too big at line %d\n", line);
- exit(1);
- }
- sprintf(regs[regno], " { \"%s\", %d, MAXSTACK, 0 },\n",
- name, atoi(nr));
- regno++;
- }
-
- void
- finish(void)
- {
- int i;
-
- /* Generate instruction table */
- for (i = 0; i < 256; i++) {
- if (opcode[i][0] != 0) {
- fputs(opcode[i], sout);
- }
- else {
- fputs(" { 0, 0, 0, i_soft, gen_UNKNOWN },\n", sout);
- }
- }
- fputs("\n};\n", sout);
-
- fputs("\nnativeReg registerFile[] = {\n", sout);
- for (i = 0; i < regno; i++) {
- fputs(regs[i], sout);
- }
- fputs("};\n", sout);
-
- fprintf(bouth, "\n#endif\n");
- }
-
- int
- countTypes(void)
- {
- int count = 0;
-
- for (;;) {
- skipSpace();
- if (buf[0] == ',') {
- buf++;
- }
- else if (buf[0] == ')') {
- return (count);
- }
- else if (buf[0] == ';') {
- buf++;
- return (count);
- }
- skipSpace();
- if (strncmp(buf, "none", 4) == 0) {
- buf += 4;
- count = 0;
- }
- else if (strncmp(buf, "any", 3) == 0) {
- buf += 3;
- count += 1;
- }
- else if (strncmp(buf, "int", 3) == 0) {
- buf += 3;
- count += 1;
- }
- else if (strncmp(buf, "long", 4) == 0) {
- buf += 4;
- count += 2;
- }
- else if (strncmp(buf, "float", 5) == 0) {
- buf += 5;
- count += 1;
- }
- else if (strncmp(buf, "double", 6) == 0) {
- buf += 6;
- count += 2;
- }
- else if (strncmp(buf, "objref", 6) == 0) {
- buf += 6;
- count += 1;
- }
- }
- }
-
- void
- getLine(void)
- {
- static char lbuf[MAXBUF];
- line++;
- buf = fgets(lbuf, sizeof(lbuf), in);
- }
-
- void
- skipSpace(void)
- {
- while (isspace(*buf)) {
- buf++;
- }
- }
-